import time
import json
import threading
from linkkit import linkkit  # 需要安装:pip install paho-mqtt==1.4.0 和 pip install aliyun-iot-linkkit(上报数据要用到)
# from app01 import models
from asgiref.sync import async_to_sync


# ################################ 上报服务器 ################################
def submit(message, channel_layer_manager):
    from app01 import models
    formData = message['formData']
    IotData = message['IotData']
    # 确认是哪种数据类型,转换后,再给平台发送
    # 1. 从设备数据库中查找到此设备的关联产品的toID(正向查询)
    device_name = IotData.get('device_name')
    device_name_alias = IotData.get('device_name_alias')
    device_secret = IotData.get('device_secret')
    device = models.Device.objects.filter(device_name=device_name,
                                          device_name_alias=device_name_alias,
                                          device_secret=device_secret,
                                          ).first()
    product = device.toProduct
    # 2. 从产品的toID查找到此产品关联的功能定义(反向查询)
    funDefine = product.fundefine_set.all()
    # 3.从formData中找跟funDefine匹配的功能定义数据类型,转为对应的数据类型,再传给阿里物联网平台
    for key, value in formData.items():
        for item in funDefine:
            Identifier = item.Identifier
            dataType = item.dataType
            if Identifier == key and dataType <= 5:
                # print('key值：', key)
                # print('value值：', value)
                # formData[key] = int(value)
                formData[key] = convert_to_number(value)
                # print('formData值：', formData)
    payload = "{'params':%s}" % formData
    # [0]id, [1]enable是否被管理, [2]accessKey进入的是哪个平台, [3]accessSecret进入平台密钥,
    # [4]iotInstanceId实例ID, [5]iotInstanceId实例ID别名, [6]clientId客户端ID, [7]host_name主机名,
    # [8]consumerGroupId消费组, [9]product_key产品ID, [10]product_key_alias产品ID别名,
    # [11]device_name设备名, [12]device_name_alias设备名别名, [13]device_secret设备密钥
    # iot = dictIot['']
    iot = IotData['iotInstanceId']
    host_name = IotData['host_name']
    product_key = IotData['product_key']
    device_name = IotData['device_name']
    device_secret = IotData['device_secret']

    pub_topic = '/sys/%s/%s/thing/event/property/post' % (product_key, device_name)  # 这个主题直接改变硬件属性值
    endpoint = "%s.mqtt.iothub.aliyuncs.com" % iot

    def connection_sub():
        # host_name+设备三元组
        lk = linkkit.LinkKit(host_name=host_name, product_key=product_key, device_name=device_name,
                             device_secret=device_secret)
        lk.config_mqtt(endpoint=endpoint)  # 产品链接
        lk.config_device_info("Eth|03ACDEFF0032|Eth|03ACDEFF0031")  # 默认
        lk.config_mqtt(port=8883, protocol="MQTTv311", transport="TCP", secure="TLS")  # 默认
        lk.connect_async()
        lk.start_worker_loop()

        time.sleep(0.9)  # 不加要出错,应该是异步的原因

        rc, mid = lk.publish_topic(pub_topic, payload, qos=1)

        if rc == 0:
            print("发布成功:%r, mid:%r" % (rc, mid))
        else:
            print("发布失败:%r, mid:%r" % (rc, mid))

        lk.destruct()  # 断开

        # # 发送到共享队列，给前端发送过去,更新页面(显示是否发布成功)
        data8 = json.dumps({'stateMid': rc})  # 字典需要序列化成json字符串
        async_to_sync(channel_layer_manager.channel_layer.group_send)(
            device_name,  # group组
            {
                "type": "send.data",  # 去调用send_data()函数
                "message": data8,  # 在send_data()里发送data8数据
            }
        )

    thread_1 = threading.Thread(target=connection_sub)
    thread_1.start()


# ############################## 字符串转数字 ####################################################
def convert_to_number(s):
    # if s.lstrip().startswith('-'):
    #     return s
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            try:
                return complex(s)
            except ValueError:
                # print('s:', s)
                return 0  # 无法转换，返回None或其他指示失败的值
